package com.tengju.bff.interfaces.manage.star;

import com.tengju.bff.interfaces.manage.star.facade.StarSignManageFacade;
import com.tengju.bff.interfaces.manage.star.vo.ListBlackUserDetailVO;
import com.tengju.bff.interfaces.manage.star.vo.ListStarAuditRecordVO;
import com.tengju.bff.interfaces.manage.star.vo.StarAuditDetailVO;
import com.tengju.bff.interfaces.shared.ApiResponse;
import com.tengju.bff.interfaces.shared.SignAssembler;
import com.tengju.bff.interfaces.shared.servlet.ManageEntrance;
import com.tengju.bff.interfaces.shared.servlet.ManageUtil;
import com.tengju.bff.interfaces.shared.servlet.NotTokenValid;
import com.tengju.user.application.archives.StarSignService;
import com.tengju.user.application.archives.dto.*;
import com.tengju.user.domain.model.sign.SignStatisticsDetail;
import com.tengju.user.domain.model.sign.StarContractEvent;
import com.tengju.user.domain.model.sign.StarSignTriggerTypeEnum;
import com.tengju.user.domain.model.user.ManageUser;
import com.tengju.user.domain.model.user.StarLevelEnum;
import com.tengju.user.domain.model.user.StarRoleEnum;
import com.tengju.user.domain.model.user.UserIdCode;
import com.tengju.user.domain.shared.*;
import com.tengju.user.domain.model.user.*;
import com.tengju.user.domain.shared.DateUtil;
import com.tengju.user.domain.shared.ResultCodeEnum;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.io.*;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Validated
@RestController
@Api(tags = "星级签约后台管理")
@RequestMapping(value = "manage/star/sign")
@Slf4j
@ManageEntrance
public class StarSignManageController {

    @Autowired
    StarSignService starSignService;

    @Autowired
    StarSignManageFacade starSignManageFacade;

    @RequiresRoles("sso")
    @ApiOperation(value = "DT后台星级审批记录列表", notes = "dt后台星级审批记录列表")
    @RequestMapping(value = "getStarAuditList", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ApiResponse<ListStarAuditRecordVO> getStarAuditList(@Valid @RequestBody StarAuditQueryDTO starAuditQueryDTO, BindingResult bindingResult) throws Exception {
        ListStarAuditRecordVO listStarAuditRecordVO = starSignManageFacade.getListStarAuditList(starAuditQueryDTO);
        return ApiResponse.newSuccess(listStarAuditRecordVO);
    }

    @RequiresRoles("sso")
    @ApiOperation(value = "DT后台星级审批记录详情", notes = "dt后台星级审批记录详情")
    @ApiImplicitParam(name = "auditId", value = "审批记录主键id", required = true, dataType = "Long")
    @RequestMapping(value = "getStarAuditDetail", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ApiResponse<StarAuditDetailVO> getStarAuditDetail(@NotNull @RequestParam Long auditId) {
        return ApiResponse.newSuccess(starSignManageFacade.getStarAuditDetail(auditId));
    }

    @RequiresRoles("sso")
    @ApiOperation(value = "DT后台黑卡列表", notes = "dt后台黑卡列表")
    @RequestMapping(value = "getBlackList", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ApiResponse<ListBlackUserDetailVO> getBlackList(@Valid @RequestBody BlackListQueryDTO blackListQueryDTO, BindingResult bindingResult) {
        ListBlackUserDetailVO listBlackUserDetailVO = starSignManageFacade.getListBlackList(blackListQueryDTO);
        return ApiResponse.newSuccess(listBlackUserDetailVO);
    }

    @RequiresRoles("sso")
    @ApiOperation(value = "DT后台黑卡详情信息", notes = "dt后台黑卡详情信息")
    @ApiImplicitParam(name = "idCode", value = "黑卡idCode", required = true, dataType = "Long")
    @RequestMapping(value = "getBlackDetail", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ApiResponse<StarAuditDetailVO> getBlackDetail(@NotNull @Min(value = 1) @RequestParam Long idCode) {
        return ApiResponse.newSuccess(starSignManageFacade.getBlackDetail(idCode));
    }

    @RequiresRoles("sso")
    @ApiOperation(value = "DT后台星级记录批量审批", notes = "dt后台星级记录批量审批")
    @RequestMapping(value = "batchUpdateAuditStar", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ApiResponse<Boolean> batchUpdateAuditStar(@Valid @RequestBody BatchStarAuditUpdateDTO batchStarAuditUpdateDTO, BindingResult bindingResult) {
        Staff staff = ManageUtil.getOperateUser();
        return ApiResponse.newSuccess(starSignService.batchAuditStar(batchStarAuditUpdateDTO, staff));
    }

    @RequiresRoles("sso")
    @ApiOperation(value = "DT后台终止签约流程", notes = "终止签约流程")
    @RequestMapping(value = "batchStopSign", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ApiResponse<Boolean> batchStopSign(@RequestBody BatchStopSignDTO batchStopSignDTO) {
        Staff staff = ManageUtil.getOperateUser();
        return ApiResponse.newSuccess(starSignService.batchStopSign(
                Optional.ofNullable(batchStopSignDTO.getTargetIdCodes())
                        .map(list -> list.stream()
                                .filter(Objects::nonNull)
                                .map(UserIdCode::new)
                                .collect(Collectors.toList())
                        ).orElse(null),
                staff));
    }

    @RequiresRoles("sso")
    @ApiOperation(value = "DT后台批量邀请入星", notes = "dt后台批量邀请入星")
    @RequestMapping(value = "batchAddStar", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ApiResponse<Boolean> batchAddStar(@Valid @RequestBody BatchStarAddDTO batchStarAddDTO, BindingResult bindingResult) {
        Staff staff = ManageUtil.getOperateUser();
        Integer targetStarLevel = batchStarAddDTO.getTargetStarLevel();
        StarRoleEnum targetStarRole = StarLevelEnum.getStarRoleCodeByLevel(targetStarLevel);
        if (targetStarRole == null) {
            return ApiResponse.newFailure(ResultCodeEnum.STAR_INVALID);
        }
        batchStarAddDTO.setTargetStarRole(targetStarRole.getCode());
        return ApiResponse.newSuccess(starSignService.batchInviteStar(batchStarAddDTO, StarSignTriggerTypeEnum.MANAGE_HANDLE, staff));
    }

    @RequiresRoles("sso")
    @ApiOperation(value = "DT用户生成入星数据", notes = "DT用户生成入星数据")
    @RequestMapping(value = "addStarData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ApiResponse<Boolean> addStarData(@Valid @RequestBody AddStarDTO addStarDTO, BindingResult bindingResult) {
        StarContractEvent event = new StarContractEvent(
                UserIdCode.of(addStarDTO.getIdCode()),
                addStarDTO.getContractId(),
                addStarDTO.getContractType(),
                DateUtil.dateToLocalDateTime(DateUtil.parseStringToDate(DateUtil.DATE_DAY_FORMAT, addStarDTO.getContractSignDate()))
        );
        starSignService.addStarData(event);
        return ApiResponse.newSuccess(true);
    }

    @ApiOperation(value = "导出签约统计数据", notes = "导出签约统计数据")
    @RequestMapping(value = "downloadSignStatisticsDetail", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @NotTokenValid
    public void downloadSignStatisticsDetail(HttpServletResponse response) {
        List<SignStatisticsDetail> signStatisticsDetailList = starSignManageFacade.listSignStatisticsDetail();
        byte[] buffer = SignAssembler.statisticsDetailsToByte(signStatisticsDetailList);
        OutputStream outputStream = null;
        try {
            if (null != buffer) {
                String dateTime = DateUtil.formartLocalDateTime("yyyy年MM月dd日HH时mm分", LocalDateTime.now());
                String fileName = URLEncoder.encode(dateTime + "签约数据" + ".csv", "UTF-8");
                response.setContentType("application/download;charset=UTF-8");
                response.setContentType("Content-type:application/vnd.ms-excel;charset=UTF-8");
                response.setHeader("Content-disposition", "attachment;filename="+fileName);
                outputStream = response.getOutputStream();
                outputStream.write(buffer);
                outputStream.flush();
            }
        } catch (Exception e) {
            log.error("导出签约统计数据异常",e);
        } finally {
            if (null != outputStream) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error("签约明细下载关闭输出流异常", e);
                }
            }
        }
    }


    @ApiOperation(value = "导出星级名单统计数据", notes = "导出星级名单统计数据")
    @RequestMapping(value = "downloadStarStatisticsDetail", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public void downloadStarStatisticsDetail(HttpServletResponse response) {
        List<SignStatisticsDetail> signStatisticsDetailList = starSignManageFacade.starList(StarLevelEnum.CITY_STAR_ONE);
        byte[] buffer = SignAssembler.starListToByte(signStatisticsDetailList);
        OutputStream outputStream = null;
        try {
            if (null != buffer) {
                String dateTime = DateUtil.formartLocalDateTime("yyyy年MM月dd日HH时mm分", LocalDateTime.now());
                String fileName = URLEncoder.encode(dateTime + "星级名单" + ".csv", "UTF-8");
                response.setContentType("application/download;charset=UTF-8");
                response.setContentType("Content-type:application/vnd.ms-excel;charset=UTF-8");
                response.setHeader("Content-disposition", "attachment;filename="+fileName);
                outputStream = response.getOutputStream();
                outputStream.write(buffer);
                outputStream.flush();
            }
        } catch (Exception e) {
            log.error("导出签约统计数据异常",e);
        } finally {
            if (null != outputStream) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error("签约明细下载关闭输出流异常", e);
                }
            }
        }
    }

}
